/**
 * Created by 小黑 on 2017/10/19.
 */

function Event () {
    this.eventList = {}
}

Event.prototype.on = function ( key, fn ) {
    if( ! this.eventList[ key ] ){
        this.eventList[ key ] = [];
    }
    this.eventList[ key ].push(fn);
};

Event.prototype.emit = function () {
    var key = Array.prototype.shift.apply(arguments),
        cache = this.eventList[key];
    if( cache ){
        for(var i = 0, fn; fn = cache[i++];){
            fn.apply(this, arguments);
        }
    }
};

Event.prototype.remove = function ( key, fn ) {
    var cache = this.eventList[key];

    if( cache ){
        if(fn){
            for(var i = 0, itemFn; itemFn = cache[i++];){
                if ( fn === itemFn ){
                    cache.splice( i, 1 );
                }
            }
        }else{
            this.eventList[key] = [];
        }
    }
};

var utils = {
    getParams : function ( i ) {
        var url = window.location.href;
        var params = url.split('/');

        return params[params.length - (i + 1)];
    },

    getQueryString: function( name ){
        var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i"),
            r = window.location.search.substr(1).match(reg),
            context = "",
            queryValue;
        if ( r !== null ) context = r[2];

        reg = null;
        r = null;

        queryValue = context === null || context === "" || context === "undefined" ? "" : context;
        return queryValue;
    },

    //获取cate和tag的name
    setDataItem : function ( val , key ) {
        var _self = this;
        if( key === 'tags' ){
            return  val.map( function (item) {
                return _self.getText(globalData.tags, item.tag_id );
            });
        }else{
            return  _self.getText( globalData.cates, val )
        }
    },

    //判断是否在数字范围
    checkNum: function (value) {
        var Regx = /^[0-9]*$/;
        if(Regx.test(value)) {
            return true;
        }else{
            return false;
        }
    },

    getText : function (targetArr, id){
        var i = 0,
            name = '',
            len = targetArr.length;

        for( i; i < len; i++){
            if(id !== 0 && targetArr[i].id === id){
                name =  targetArr[i].name;
                break;
            }
        }
        return name;
    },

    getLocalTime: function (nS) {
        Date.prototype.toLocaleString = function () {
            return this.getFullYear() + "-" + ( this.getMonth() + 1 < 10 ? '0' + ( this.getMonth() + 1 ) : this.getMonth() + 1 )  + "-" + this.getDate();
        };
        //return new Date(parseInt(nS) * 1000).toLocaleString().replace(/\//g,'-');
        return new Date(parseInt(nS) * 1000).toLocaleString();
    },

    getRandomColor: function ( opacity ) {
            var r = Math.floor(Math.random()*255),
                g = Math.floor(Math.random()*255),
                b = Math.floor(Math.random()*255),
                o = opacity || 1;
            return 'rgba('+ r +','+ g +','+ b +','+ o +')';

    },

    parseTmpl : function( html, data ) {
        var re = /{%([^%>]+)?%}/g,
            reExp = /(^( )?(if|for|else|switch|case|break|{|}))(.*)?/g,
            code = 'var r=[];\n',
            cursor = 0,
            match;
        var add = function(line, js) {
            js
                ? (code += line.match(reExp)
                ? line + '\n'
                : 'r.push(' + line + ');\n')
                : (code += line != '' ? 'r.push("' + line.replace(/"/g, '\\"') + '");\n' : '');
            return add;
        };

        while( match = re.exec( html ) ) {
            add(html.slice(cursor, match.index))(match[1], true);
            cursor = match.index + match[0].length;
        }

        add( html.substr(cursor, html.length - cursor) );
        code += 'return r.join("");';
        //防注入 ： 安全性
        var render = new Function("data", code.replace(/[\r\t\n]/g, ''));
        return render( data );
    }
};

function LoadData( opts ) {
    this.init(opts);
}

LoadData.prototype.init = function (opts) {
    var _self = this;
    _self.page = opts.page || 1;

    _self.renderModule = $.fn.render({
        template: opts.template,
        handleFn: opts.handleFn,
        insertTarget: opts.lists,
        method: opts.method,
        renderFn: opts.renderFn || '',
        beforeRender: opts.beforeRender,
        afterRender: opts.afterRender
    });

    //绑定加载
    _self.load = $(opts.btn).loadMore({
        loadBtn: opts.btn,
        loadingAnim: opts.loadingAnim,
        loadingAnimDom: opts.loadingAnimDom,
        loadedEmptyFn: opts.loadedEmptyFn,
        loadFn: function ( me ) {
            me.willLoad();
            if(! ($ && $ === jQuery) ){
                throw Error('$ is undefined');
            }else{
                $.ajax({
                    type: "GET",
                    url: opts.url,
                    data: {
                        page : _self.page ++,
                        type : opts.paramType,              //手游或者在线
                        limit : opts.paramLimit
                    },
                    dataType:"json",
                    success: function ( res ) {
                        if( res.ret === 0 ){
                            var lists = res.data[ opts.listType + '_list' ];
                            if( lists.length ){
                                _self.renderModule.reRender( lists, _self.page );
                            }else{
                                if( _self.loadedEmptyFn && typeof _self.loadedEmptyFn === 'function'){
                                    _self.loadedEmptyFn( _self.load );
                                }
                            }
                            if( res.data.all_page && _self.page > res.data.all_page ){
                                me.finishLoad( true );
                            }else{
                                me.finishLoad();
                            }
                        }else{
                        }
                    }
                });
            }
        },
        fullLoadFn: opts.fullLoadFn || function (me) {
            me.$loadBtn.css({
                "background-color": "transparent",
                "cursor":"text"
            });
            me.$loadBtn.text( "已经到底啦！" );
            me.$loadBtn.off( "click" );
        }
    });

    //如果需要首屏渲染
    if( opts.initialFirstScreen ){
        _self.page = 1;
        if( opts.initialFirstFn && typeof opts.initialFirstFn === 'function'){
            //预留首屏渲染钩子
        }else{
            _self.load.runLoadFn( _self.load );
        }

    }
};

/**
 * loadMore插件
 *  */
;(function ($) {
    'use strict';

    $.fn.loadMore = function ( options ) {
        return new myLoadMore( this, options )
    };

    var myLoadMore = function ( element, options ) {
        var _self = this;
        _self.init( element, options );
    };

    myLoadMore.prototype = {
        constructor: myLoadMore,
        init: function ( element,  options ) {
            var _self = this;
            _self.lock = false;                         //是否正在发送数据的状态值
            _self.opts = $.extend( true, {}, {
                loadBtn: element,
                loadingAnim: false,
                loadingAnimDom : '',
                loadFn: '',
                loadedEmptyFn: '',
                fullLoadFn: ''
            }, options );

            //判断是否存在，抛出错误
            _self.$loadBtn          =   $( _self.opts.loadBtn );

            _self.loadingAnim       =   _self.opts.loadingAnim;
            _self.$loadingAnimDom   =   $( _self.opts.loadingAnimDom );

            _self.loadFn            =   _self.opts.loadFn;
            _self.loadedEmptyFn     =   _self.opts.loadedEmptyFn;
            _self.fullLoadFn        =   _self.opts.fullLoadFn;

            if( !_self.lock ){
                _self.$loadingAnimDom.hide();
            }
            if(_self.$loadBtn){
                bindEvent(_self, 'click');
            }
        },

        willLoad: function () {
            var _self = this;
            _self.lock = true;
            if( _self.loadingAnim ){
                // 判断 抛出错误 me.$loadingAnimDom && me.$targetList
                _self.$loadingAnimDom.show();
            }
        },

        finishLoad: function( end ) {
            var _self = this;
            _self.lock = false;
            if( _self.loadingAnim ){
                // 判断 抛出错误 me.$loadingAnimDom && me.$targetList
                _self.$loadingAnimDom.hide();
            }

            if( end && _self.fullLoadFn && ( typeof _self.fullLoadFn === 'function' ) ){
                _self.fullLoadFn( _self );
            }
        },

        runLoadFn: function ( me ) {
            if( me.loadFn && typeof me.loadFn === 'function' ){
                me.loadFn( me );
            }
        }
    };

    function bindEvent( me, eventType ) {
        var $selector = me.$loadBtn;
        $selector.on( eventType, function (event) {
            event.preventDefault();
            me.runLoadFn(me);
        });
    }


})(window.jQuery);

/**
 * render插件
 * 需要：提供钩子，对插入之后的dom进行一些事件绑定
 *  */
;(function ($) {
    'use strict';

    $.fn.render = function ( options ) {
        return new render( this, options )
    };

    var render = function ( element, options ) {
        var _self = this;
        _self.init( options );
    };

    render.prototype = {
        constructor: render,
        init: function ( options ) {
            var _self = this;
            _self.opts = $.extend( true, {}, {
                insertTarget: '',               //插入目标
                template: '',                   //渲染模板
                handleFn: {},                   //对指定字段的映射函数
                beforeRender: '',               //渲染前
                afterRender: '',                //渲染后
                method: 'append'                //插入方法
            }, options );

            if(_self.opts.insertTarget ){
                _self.$insertTarget = _self.opts.insertTarget instanceof jQuery
                    ? _self.opts.insertTarget
                    : $( _self.opts.insertTarget );
            }

            _self.renderFn = _self.opts.renderFn || '';
            _self.beforeRender = _self.opts.beforeRender;
            _self.afterRender = _self.opts.afterRender;
        },

        reRender: function ( data, page ) {
            var _self = this;
            var handles = _self.opts.handleFn;
            if( data instanceof Array ){
                _self.mapData = data.map(function (item) {
                    return handleData( handles, item )
                })
            }else{
                _self.mapData = handleData( handles, data );
            }

            if( _self.beforeRender && typeof _self.beforeRender === 'function' ){
                _self.beforeRender( page );
            }
            var fragmentDocument = renderData(  _self  );
            addDOM( _self, fragmentDocument );
            //添加钩子
            if( _self.afterRender && typeof _self.afterRender === 'function' ){
                _self.afterRender.bind(_self)();
            }
        }

    };

    function handleData( handles, item ) {
        var mapData = item;
        $.each( handles, function ( key, fn ) {
            if( mapData[ key ] ){
                // 如果data中的属性值存在映射函数，则进行转换
                // 有坑 传值
                mapData[ key ] = fn.call( this, mapData[key], key );
            }
        });

        return mapData;

    }

    function renderData( _self ) {
        var tmpl = _self.opts.template,
            data = _self.mapData,
            html = '';

        if( _self.renderFn || typeof _self.renderFn === 'function'  ){
            html = _self.renderFn( tmpl, data );
        }else{
            //默认模板是列表项
            if ( data instanceof Array ){
                $.each( data, function ( index, item ) {
                    html += utils.parseTmpl( tmpl , item );
                })
            }else if( data instanceof  Object ){
                html = utils.parseTmpl( tmpl , data )
            }
        }

        return html;
    }

    function addDOM( _self, fragmentDocument ) {
        var $selector = $( _self.opts.insertTarget ),
            method = _self.opts.method;
        $selector[ method ](fragmentDocument);
    }

})(window.jQuery);

/**
 * slideTab组件
 * $().slideTab({
        nodes: {
            slideTab : '.slide-tabs',               //slideTabs组件
            tabThumb : '.tab-thumb',                //tab列表
            thumbItems : '.tab-thumb-item',         //tab列表项数组
            panelContainer : '.tab-container',      //panel外框
            panelWrapper : '.tab-panel-wrapper',
            panelItems : '.tab-panel',              //面板项
            slideBar : '.tab-slideBar'              //滑条
        }
    })
 * create By kira
 */
;(function ($) {
    'use strict';


    $.fn.slideTab = function ( options ) {
        return new mySlideTab( this, options )
    };

    var mySlideTab = function ( element, options ) {
        var _self = this;
        _self.init( options );
    };

    mySlideTab.prototype = {
        constructor: mySlideTab,
        init: function ( options ) {
            var _self = this;

            _self.opts = $.extend( true, {}, {
                nodes: {
                    slideTab : '.slide-tab',                            //slideTab容器
                    tabThumb : '.tab-thumb',                            //tab控制器容器
                    thumbItems : '.tab-thumb-item',                     //tab控制器数组
                    panelContainer : '.tab-container',                  //内容区域
                    panelWrapper : '.tab-panel-wrapper',                //slide面板的容器
                    panelItems : '.tab-panel',                          //panel面板数组
                    slideBar : '.tab-slideBar'
                },
                offset: 0,
                initTabFn: '',
                afterInitTabFn: '',
                afterChangeFn: '',
                activeClass: 'active'                                   //active时的class
            }, options );

            _self.Nodes = {};

            //获取jq元素
            $.each( _self.opts.nodes, function ( key ,val ) {
                if(val){
                    _self.Nodes['$' + key] = $(val);
                }
            });

            //初始化slide时需要用到的数据
            _self.globalAttr = {
                tabWidth:0,                     //当前tab条宽度
                panelWidth: 0,                  //当前面板的宽度
                height: 0,
                offset: 0,                      //滑条偏移
                slideWidth: 0,                  //滑条宽度
                tabNum: 0                       //面板数量
            };

            //初始化slide时需要用到的数据
            _self.globalAttr = initGlobalAttr( _self.globalAttr, _self.Nodes );

            //初始化tab组件的一些必要样式
            setStyle( _self );

            _self.afterChangeFn = _self.opts.afterChangeFn;

            //绑定tab控制器的点击事件
            _self.initTabFn = _self.opts.initTabFn;

            if( _self.initTabFn && ( typeof _self.initTabFn === 'function') ){
                _self.initTabFn( _self );
            }

            //防止样式错乱
            _self.Nodes.$panelItems.css('visibility','visible');
            _self.Nodes.$slideBar.css('visibility','visible');

            bindEvent( _self, _self.Nodes.$thumbItems );
        },

        setActiveTab: function ( target ) {
            var _self = this;
            _self.setTranslateX( target );
            _self.setActiveClass( target );
            if( _self.afterChangeFn && ( typeof _self.afterChangeFn === 'function')){
                _self.afterChangeFn( _self );
            }
        },
        //设置当前显示的tab控制器的样式
        // target currentTab DOM元素
        setActiveClass: function ( target ) {
            var _self = this,
                $target = $( target ),
                active = _self.opts.activeClass,                            //active class名
                $prevActiveNodes = $( '.' + active ),
                len = $prevActiveNodes.length,
                i = 0;
            for (i; i < len; i++){
                $($prevActiveNodes[i]).removeClass( active );
            }
            $target.addClass( active );
        },

        //slide动效 - 移动
        setTranslateX: function ( target ) {
            var _self = this,
                $target = $( target ),
                global = _self.globalAttr,
                Nodes = _self.Nodes,
                index = $target.attr('data-index'),

                panelOffsetX = global.panelWidth * index,
                slideOffsetX = global.slideWidth * index,

                $panel = Nodes.$panelWrapper,
                $slide = Nodes.$slideBar || '';

            $panel.css("transform", "translate3d(-" + panelOffsetX + "px, 0px, 0px)");
            if( $slide ){
                $slide.css("transform",  "translate3d(" + slideOffsetX + "px, 0px, 0px)");
            }
        }
    };

    function initGlobalAttr(global, Nodes ) {
        global.panelWidth = parseFloat(Nodes.$panelContainer.css("width"));
        global.tabWidth = parseFloat(Nodes.$tabThumb.css("width"));
        global.tabNum = Nodes.$panelItems.length;
        global.slideWidth = global.tabWidth / global.tabNum;

        return global;
    }

    //如果不是slide效果 则在这里进行修改
    function setStyle ( that ){
        var _self = that,
            global = _self.globalAttr,
            Nodes = _self.Nodes,
            len = global.tabNum,
            panelWidth = global.panelWidth,
            slideWidth = global.slideWidth,
            offset = Number(global.offset),
            $slideTab = Nodes.$slideTab,
            $wrapper = Nodes.$panelWrapper,
            $slideBar = Nodes.$slideBar || '',
            $panels = Nodes.$panelItems;

        $slideTab.css('position','relative');

        $wrapper.css({
            'display' : 'flex',
            'width' : (panelWidth * len + offset) + 'px',
            'transition': 'all .5s cubic-bezier(.1,.62,.12,.99)'
        });
        if( $slideBar ){
            $slideBar.css("width", slideWidth + 'px');
        }

        for(var i = 0 ; i < len ; i++){
            $($panels[i]).css("width", panelWidth + 'px');
        }
    }

    function bindEvent( _self,  selector ) {
        selector.on("click",function ( e ) {
            e = e || event;
            e.preventDefault();
            //防止冒泡
            _self.setTranslateX( e.target );            //changePanelActive
            _self.setActiveClass( e.target );           //changeTabActive
            if( _self.afterChangeFn && ( typeof _self.afterChangeFn === 'function')){
                _self.afterChangeFn( _self );
            }
        });
    }

})(window.jQuery);

/**
 * 弹出层插件
 * 将绑定按钮作为属性传入
 * 提供方法，为后续传入按钮绑定事件
 * 设定锁，防止多个事件冲突
 * create By kira
 */
;(function($) {
    'use strict';

    $.fn.SUIModel = function ( options ) {
        return new MySUIModel( this, options );
    };

    var MySUIModel = function ( element, options ) {
        var _self = this;
        _self.init( element, options );
    };

    MySUIModel.prototype = {
        construct: MySUIModel,
        init: function ( element, options ) {
            var model = this;
            model.opts = $.extend( true, {
                inAnim: 'fadeInUp',
                outAnim: 'fadeOutDown',
                shade: '',
                openFn: '',
                closeFn: ''
            }, options );

            model.$model = $( element );
            model.$shade = $( model.opts.shade ) || '';
        },

        open: function () {
            var model = this;
            if(model.opts.openFn && model.opts.openFn === 'function'){
                model.opts.openFn();
            }

            $("body")
                .height( $( window ).height() )
                .css({
                    "overflow-y": "hidden"
                });

            if( model.$shade && model.$shade instanceof jQuery){
                model.$shade
                    .height($(window).height())
                    .css({
                        "overflow-y": "hidden"
                    })
                    .fadeIn();
            }

            model.$model
                .show()
                .removeClass('animated '  + model.opts.inAnim + ' ' + model.opts.outAnim)
                .addClass('animated ' + model.opts.inAnim);
        },

        close: function () {
            var model = this;
            var timer = null;
            if(model.opts.closeFn && model.opts.closeFn === 'function'){
                model.opts.closeFn();
            }
            model.$shade.fadeOut( 1000 );

            model.$model
                .removeClass( 'animated ' + model.opts.inAnim + ' ' + model.opts.outAnim )
                .addClass( 'animated ' + model.opts.outAnim )
                .fadeOut( 700 );

            timer = setTimeout(function () {
                $("body").css({
                    "overflow-y": "auto"
                });
                clearTimeout( timer );
                timer = null;
            }, 800 )

        }
    }

})(window.jQuery);



/**
 * 分页插件
 * 将绑定按钮作为属性传入
 * create By kira
 */

;(function($) {
    'use strict';

    $.fn.pagination = function ( options ) {
        return new Pagination( this, options );
    };

    var Pagination = function ( selector, options ) {
        var _self = this;
        _self.init( selector, options );
    };

    Pagination.prototype = {
        construct: Pagination,
        init: function ( selector,options ) {
            var _self = this;
            _self.opts = $.extend( true, {
                pageId: selector,
                viewRender: {
                    parent: '',         //列表的父级
                    data: '',           //当前页的列表数据
                    render: ''          //渲染方法
                },
                dataAmount: 0,           //列表总数
                showPageLength: 3,       //最多显示的页码个数
                pageListCount: 0,        //当前列表显示个数
                activeClass: '',         //按钮样式

                //beforeJump  跳转前
                //afterJump   跳转后/ 列表渲染前
                //afterRender 渲染后
            }, options );

            _self.pageId = _self.opts.pageId;
            //初始化分页组件相关数据
            _self.currentPage    = 1;
            _self.maxPage        = 1;
            _self.dataAmount     = parseInt(_self.opts.dataAmount);
            _self.showPageLength = parseInt(_self.opts.showPageLength);
            _self.pageListCount  = parseInt(_self.opts.pageListCount);

            //初始化列表渲染相关数据
            _self.listParent     = _self.opts.viewRender.parent;
            _self.listData       = _self.opts.viewRender.data;
            _self.renderMethod   = _self.opts.viewRender.render;

            //初始化三个钩子
            _self.beforeJump    = _self.opts.beforeJump;
            _self.afterJump     = _self.opts.afterJump;
            _self.afterRender   = _self.opts.afterRender;



            _self.callHook( _self.opts.initPagination, function(){
                _self.beforeCreate();
            });
        },

        //创建之前
        beforeCreate: function(){
            var _self = this;
            _self.opts.allPage ? _self.maxPage = parseInt( _self.opts.allPage ) : _self.setMaxPage();
            _self.setCurrentPage(true);
        },

        //设置最大页数
        setMaxPage : function () {
            var _self = this;
            _self.maxPage =  _self.dataAmount % _self.pageListCount > 0
                ? Math.ceil( _self.dataAmount / _self.pageListCount  )
                : Math.floor( _self.dataAmount / _self.pageListCount ) ;
        },

        //设置当前分页
        setCurrentPage: function (isCreate) {
            var _self = this;
            _self.callHook(isCreate ? null : _self.beforeJump, function(){
                _self.renderPageView();
                _self.initPageBtnEvent( _self.dataAmount );
            });
        },

        //绑定点击事件
        initPageBtnEvent: function(){
            var _self = this;
            $(_self.pageId)
                .off('click','[page-data]')
                .on('click' ,'[page-data]', function(e){
                    e = e || event;
                    e.preventDefault();
                    _self.currentPage = Number($(e.target).attr('page-data'));
                    _self.setCurrentPage();
                })
        },

        //渲染当前分页视图
        renderPageView: function () {
            var _self = this;
            var paginationHtml = '', listHtml = '';

            //渲染分页

            paginationHtml = getPageRenderHtml( _self.currentPage, _self.maxPage, _self.showPageLength );

            $( _self.pageId ).html(paginationHtml);

            _self.callHook( _self.afterJump, function(){
                //渲染列表
                if(_self.renderMethod){
                    listHtml =_self.callHook( _self.renderMethod, _self.listData );
                }else{
                    _self.callHook( getListRenderHtml, _self.listData );
                    $(_self.listParent).html(listHtml);
                }
                _self.callHook( _self.afterRender);
            });
        },

        //钩子
        callHook(){
            var _self = this, next,
                callback = Array.prototype.splice.apply(arguments, [0, 1])[0];
            if( callback &&(typeof callback ) === 'function' ){
                return callback.apply(_self, arguments );
            }else{
                next = Array.prototype.splice.apply(arguments, [0, 1])[0];
                if( next && (typeof next ) === 'function' ){
                    next.apply(_self, arguments );
                }
            }
        },

    };

    //获取分页字符串
    function getPageRenderHtml(currentPage, maxPage, length){
        var prev = currentPage > 1 ? currentPage - 1 : 1,
            next = currentPage < maxPage ? currentPage + 1 : maxPage;
        return  `
            <div class="page-container">
                <div class="${ currentPage > 1 ? '': 'page-item-disable' }" page-data="1" page-rel="firstPage">
                    首页
                </div>
                <div class="${ currentPage > 1 ? 'page-item': 'page-item page-item-disable' }" page-data="${ prev }" page-rel="prevPage">
                    <
                </div>
                ${(function(){
            var minPage = 1, len = length, str = '';
            if( maxPage < length ){
                len = maxPage;
            }

            if( currentPage - Number(len / 2 ) > 0 && currentPage + Number( len / 2 ) <= maxPage ){
                minPage = currentPage - parseInt( len / 2 );
            }else if( currentPage - Number( len / 2 ) > 0 && currentPage + Number( len / 2 ) > maxPage){
                minPage = maxPage - len + 1;
                if( minPage <= 0 ){
                    minPage = 1;
                }
            }

            for(let i = 0; i< len; i++){
                let num = minPage++;
                let itemPageClass = "page-item";

                if( num === currentPage ){
                    itemPageClass = "page-item page-item-active";
                }
                str +=`<div class="${itemPageClass}" page-data="${num}" page-rel="itemPage">${num}</div>`;

            }

            return str;
        })()}
                <div class="${ currentPage < maxPage ? 'page-item' : 'page-item page-item-disable' }" page-data="${ next }" page-rel="nextPage">
                   >
                </div>
                <div class="${ currentPage < maxPage ? '' : ' page-item-disable' }" page-data="${ maxPage }" page-rel="lastPage">
                    尾页
                </div>
            </div>
        `;
    }

    function getListRenderHtml(data){
        var str = '';
        if(data instanceof Array){
            data.forEach(function(item, index){
                str += `<div>${item}</div>`
            });
        }else if(typeof data === 'string'){
            str += `<div>${data}</div>`
        }
        return str;
    }

})(window.jQuery);